﻿namespace IBTrader.Model
{
    using IBTrader.Modules;
    using IBTrader.Modules.Configuration;
    using NLog;
    using System;
    using System.Collections;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Xml.Serialization;

    public class Store
    {
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();
        #region properties
        public Contracts Contracts { get; set; }
        public HistoricalContracts HistoricalContracts { get; set; }
        public Algos Algos { get; set; }
        public Orders Orders { get; set; }
        public Dones Dones { get; set; }
        public BacklogConfigurations BacklogConfigurations { get; set; }
        private void SetProperties(Action<PropertyInfo> call)
        {
            GetType().GetProperties().ToList().ForEach(p => call(p));
        }
        #endregion
        public Store() { }
        public Store(string fileFormat)
        {
            this.fileFormat = fileFormat;
            SetProperties(p => p.SetValue(this, Activator.CreateInstance(p.PropertyType), null));
        }
        #region done
        internal bool HasDone(string action)
        {
            bool done = GetDone(action);

            if (!done)
                Dones.Add(new Done { Action = action });

            return done;
        }
        internal bool GetDone(string action)
        {
            return Dones.Any(k => k.Action == action);
        }
        #endregion
        #region read/write
        private readonly string fileFormat;
        private static readonly CultureInfo ci = CultureInfo.InvariantCulture;
        public void Read(object _, EventArgs __)
        {
            W.X(logger, () =>
            {
                if (File.Exists(FileName()))
                    using (var file = File.OpenText(FileName()))
                    {
                        var store = new XmlSerializer(GetType()).Deserialize(file) as Store;
                        SetProperties(p =>
                        {
                            var source = p.GetValue(store, null) as IList;
                            var target = p.GetValue(this, null) as IList;
                            if (target is Dones) return; // we don't want to restore that
                            foreach (var item in source)
                            {
                                target.Add(item);
                                if (item is IStoreMember)
                                    (item as IStoreMember).Store = this;
                            }
                        });
                    }
                if (!Algos.Any()) Algos.Add(new Algo(this)); // simplify trader vm
            });
        }
        public void Write(object _, EventArgs __)
        {
            W.X(logger, () =>
            {
                using (var file = File.CreateText(FileName()))
                    new XmlSerializer(GetType()).Serialize(file, this);
            });
        }
        private string FileName()
        {
            return string.Format(fileFormat, DateTime.Now.ToString(Times.DateFormat, ci));
        }
        #endregion
    }
}